/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "device/manager.h"
#include "utils.h"
#include <mc/log.h>
#include <mc/json.h>

namespace devmon {

void device_manager::add_device(mc::engine::service* service, const std::string& csr_file,
                                mc::dict connector) {
    device_csr dev_csr;
    dev_csr.init(mc::json::json_decode(csr_file), connector);
    auto result = dev_csr.process_topology_object();

    auto [device_object, drv_ptr] = dev_csr.create_devices_object(service);
    if (device_object == nullptr || drv_ptr == nullptr) {
        elog("create devices object failed");
        return;
    }

    auto position = connector["GroupPosition"].as_string();
    device_topo::get_instance().add_device_object(
        position, mc::shared_ptr<mc::engine::abstract_object>(device_object));

    if (result.contains("topology") && result.contains("objects") &&
        result["topology"].is_dict() && result["objects"].is_dict() &&
        result["topology"].as_dict().contains("Anchor")) {
        device_topo::get_instance().add_topology(result["topology"].as_dict(),
                                                 result["objects"].as_dict(), position);
    }

    // 在拓扑添加完成后完成设备设置（创建子设备、通用设备并启动业务）
    dev_csr.finalize_device_setup(service, device_object, *drv_ptr);
}

void device_manager::remove_device(const mc::dict& connector) {
    auto position = utils::get_connector_position(connector);
    if (position.empty()) {
        elog("position: ${position}, get position failed", ("position", position));
        return;
    }
    auto device_object = device_topo::get_instance().get_device_object(position);
    if (!device_object) {
        elog("position: ${position}, device object not found", ("position", position));
        return;
    }
    
    // 使用 utils 函数安全地获取 unit 信息
    auto unit_opt = utils::get_connector_unit(connector);
    if (!unit_opt.has_value()) {
        elog("position: ${position}, get unit info failed", ("position", position));
        return;
    }
    
    try {
        unit& unit_info = unit_opt.value();
        device_driver& driver = unit_info.load_compatible_driver();
        device_driver_t& device = driver.get_device(unit_info.m_type);
        device.stop(device_object.get());
        device_topo::get_instance().remove_device_object(position);
    } catch (const std::exception& e) {
        elog("position: ${position}, remove device failed, error: ${error}", 
             ("position", position)("error", e.what()));
        return;
    }
}

} // namespace devmon
    